import { DeltaOperation } from 'quill'
import { Pares, Node } from './parse'
import { QuillDeltaToHtmlConverter } from 'quill-delta-to-html'

const removeObjectEmptyValue = <T extends Record<string, any>>(obj: T): T => {
    Object.keys(obj).forEach(key => {
        if (obj[key] === undefined) {
            Reflect.deleteProperty(obj, key)
        }
    })
    return obj
}
export const handleStyleStrToObj = (styleStr: string) => {
    const styleObj: Record<string, string> = {}
    if (!styleStr?.trim()) return styleObj
    styleStr?.trim()?.split(';').forEach((item: string) => {
        const [key, value] = item.split(':')
        styleObj[key] = value
    })
    return styleObj
}

export const handleStyleObjToStr = (styleObj: Record<string, string>) => {
    return Object.entries(styleObj).map(([key, value]) => `${key}:${value}`).join(';')
}


const class_font_size_map = {
    'font-size-12': 12,
    'font-size-16': 17,
    'font-size-20': 21,
    'font-size-23': 24,
}

/** html 是从cut-off-1开始，delta 是从data-type=0开始 */
const line_height_map = {
    '1': 1,
    '2': 2,
    '3': 4,
    '4': 16,
    '5': 16,
    '6': 64,
}

const class_color_map = {
    'color-blue-01': '#56c1fe',
    'color-lblue-01': '#73fdea',
    'color-green-01': '#89fa4e',
    'color-yellow-01': '#fff359',
    'color-pink-01': '#ff968d',
    'color-purple-01': '#ff8cc6',

    'color-blue-02': '#02a2ff',
    'color-lblue-02': '#18e7cf',
    'color-green-02': '#60d837',
    'color-yellow-02': '#fbe231',
    'color-pink-02': '#ff654e',
    'color-purple-02': '#ef5fa8',

    'color-blue-03': '#0176ba',
    'color-lblue-03': '#068f86',
    'color-green-03': '#1db100',
    'color-yellow-03': '#f8ba00',
    'color-pink-03': '#ee230d',
    'color-purple-03': '#cb297a',

    'color-blue-04': '#004e80',
    'color-lblue-04': '#017c76',
    'color-green-04': '#017001',
    'color-yellow-04': '#ff9201',
    'color-pink-04': '#b41700',
    'color-purple-04': '#99195e',

    'color-gray-01': '#d6d5d5',
    'color-gray-02': '#929292',
    'color-gray-03': '#5f5f5f',
}
/**
 * html字符串 转为按段落分割的数组
 */
const DEFAULT_FONT_SIZE = 17
export const handleHtmlToParagraph = async (html: string): Promise<ParagraphItem[]> => {
    const pargraphs: ParagraphItem[] = []
    // 根据标配分割
    const parser = new Pares()
    const nodes = parser.parse(html)
    // console.log(nodes)
    for (let node of nodes) {
        if (node.name && node.children) {
            if (['h1', 'h2', 'blockquote', 'p'].includes(node.name)) {
                const { attrs, children } = node
                const { style: styleStr = '' } = attrs || {}//style字符串转对象

                const pitem: ParagraphItem = {
                    align: 0,
                    para_type: ((name: string) => {
                        switch (name) {
                            case 'h1':
                                return PARA_TYPE.HEADER1
                            case 'h2':
                                return PARA_TYPE.HEADER2
                            case 'blockquote':
                                return PARA_TYPE.BLOCKQUOTE
                            default:
                                return PARA_TYPE.TEXT
                        }
                    })(node.name),
                    text: {
                        nodes: []
                    }
                }
                const styleObj = handleStyleStrToObj(styleStr)
                let _root_font_size = node.name === 'h1' ? 20 : node.name === 'h2' ? 18 : DEFAULT_FONT_SIZE
                // let _root_font_size = ['h1', 'h2'].includes(node.name) ? undefined : DEFAULT_FONT_SIZE
                let _root_color: string | undefined
                if (Reflect.has(styleObj, 'text-align')) {
                    const _align = styleObj['text-align']
                    if (_align === 'center') {
                        pitem.align = 1
                    } else if (_align === 'right') {
                        pitem.align = 2
                    }
                }
                const _rootStyle: Record<string, boolean> = {}
                if (node.name === 'h1' || node.name === 'h2') {
                    _rootStyle.bold = true
                }
                const fn = (children: Node[], root: {
                    rootStyle: Record<string, boolean>,
                    rootFontSize: number | undefined,
                    rootColor: string | undefined,
                }, parentNodeNameList: string[]) => {
                    const { rootStyle, rootFontSize, rootColor } = root
                    // 循环处理children
                    children.forEach(child => {
                        let _style: Record<string, boolean> = { ...rootStyle }
                        let _font_size = rootFontSize
                        let _color = rootColor
                        const attrs = child.attrs || {}
                        const styleStr = attrs.style || ''
                        const styleObj = handleStyleStrToObj(styleStr)
                        const classList: string[] = (attrs.class || '').split(' ') || []
                        if (Reflect.has(styleObj, 'text-decoration')) {
                            _style.strikethrough = true
                        }
                        if (Reflect.has(styleObj, 'color')) {
                            _color = styleObj['color']
                        }
                        classList.forEach(c => {
                            if (Reflect.has(class_color_map, c)) {
                                _color = class_color_map[c as keyof typeof class_color_map]
                            }
                            if (Reflect.has(class_font_size_map, c)) {
                                _font_size = class_font_size_map[c as keyof typeof class_font_size_map]
                            }
                        })
                        if (child.name) {
                            if ('strong' === child.name) {
                                _style.bold = true
                            } else if ('em' === child.name) {
                                _style.italic = true
                            } else if ('s' === child.name) {
                                _style.strikethrough = true
                            }
                            if ('a' === child.name && child.children?.length) {
                                // 链接类型
                                const { children, attrs } = child
                                const textnode = children[0]
                                const href = attrs?.href || ''
                                const text = textnode.text || ''
                                if (textnode && text && href) {
                                    pitem.text!.nodes.push({
                                        type: 'TEXT_NODE_TYPE_RICH',
                                        rich: {
                                            jump_url: href,
                                            orig_text: href,
                                            style: {},
                                            text: text,
                                            type: 'RICH_TEXT_NODE_TYPE_WEB',
                                        }
                                    })
                                }
                                return
                            }
                        }
                        if ((child.type === 'text' && child.text) || 'br' === child.name) {
                            // 进入文本或换行（实际根据deltaToHtml配置是不存在br标签了） 
                            // 如果文本中存在#xxx#，则视为搜索关键字
                            // 不使用关键字解析的node.name
                            const UNSET_NAME = ['blockquote']//引用 类型中不进行关键字解析
                            if (parentNodeNameList.some(e => UNSET_NAME.includes(e))) {
                                pitem.text!.nodes.push({
                                    type: 'TEXT_NODE_TYPE_WORD',
                                    word: removeObjectEmptyValue({
                                        words: child.text || '\n',
                                        color: _color,
                                        font_size: _font_size,
                                        style: _style
                                    })
                                })
                            }
                            else {
                                let _text = child.text || ''
                                //最大搜索关键字长度【30】，如果超过这个长度，则不视为搜索关键字
                                const resultList: RegExpExecArray[] = []
                                let result: RegExpExecArray | null = null
                                const regex = /#.[^#]{1,30}?#/g //#任意非空字符串#非贪婪匹配
                                const _exec = () => {
                                    while ((result = regex.exec(_text)) != null) {
                                        resultList.push(result)
                                    }
                                }
                                _exec()
                                if (!resultList.length) {
                                    // 没有匹配结果
                                    pitem.text!.nodes.push({
                                        type: 'TEXT_NODE_TYPE_WORD',
                                        word: removeObjectEmptyValue({
                                            words: child.text || '\n',
                                            color: _color,
                                            font_size: _font_size,
                                            style: _style
                                        })
                                    })
                                } else {
                                    let start = 0
                                    let end = -1
                                    for (let i = 0; i < resultList.length; i++) {
                                        const item = resultList[i]
                                        const matchText = item[0] //匹配结果
                                        const matchTextLength = matchText.length
                                        const matchTextStart = item.index
                                        if (matchTextStart === start) {
                                            start += matchTextLength
                                            // 处理连接类型
                                            pitem.text!.nodes.push({
                                                type: 'TEXT_NODE_TYPE_RICH',
                                                rich: {
                                                    jump_url: `//search.bilibili.com/?keyword=${encodeURIComponent(matchText.replaceAll('#', ''))}`,
                                                    orig_text: matchText,
                                                    text: matchText,
                                                    type: 'RICH_TEXT_NODE_TYPE_TOPIC',
                                                }
                                            })
                                            end = start
                                        } else {
                                            pitem.text!.nodes.push({
                                                type: 'TEXT_NODE_TYPE_WORD',
                                                word: removeObjectEmptyValue({
                                                    words: _text.substring(start, matchTextStart),
                                                    color: _color,
                                                    font_size: _font_size,
                                                    style: _style
                                                })
                                            })
                                            end = matchTextStart
                                            start = matchTextStart
                                            // 处理其他内容
                                            i--
                                        }
                                    }
                                    if (end < _text.length) {
                                        pitem.text!.nodes.push({
                                            type: 'TEXT_NODE_TYPE_WORD',
                                            word: removeObjectEmptyValue({
                                                words: _text.substring(end),
                                                color: _color,
                                                font_size: _font_size,
                                                style: _style
                                            })
                                        })
                                    }
                                }
                            }
                        } else if (child.children?.length) {
                            // 进入下一次遍历children
                            fn(child.children, {
                                rootStyle: _style, rootFontSize: _font_size, rootColor: _color,
                            }, [...parentNodeNameList, child.name!])
                        }
                    })
                }
                fn(children, { rootStyle: _rootStyle, rootFontSize: _root_font_size, rootColor: _root_color }, [node.name!])
                pargraphs.push(pitem)
            } else if (['ul', 'ol'].includes(node.name)) {
                const pItem: ParagraphItem = {
                    align: 0,
                    para_type: PARA_TYPE.LIST,
                    list: {
                        items: [],
                        style: node.name === 'ul' ? 2 : 1,
                    }
                }
                let order = 0
                node.children?.forEach((child) => {
                    if (child.name === 'li' && child.children?.length) {
                        order++
                        const listItem: {
                            level: number,
                            order: number,
                            nodes: TextNode[]
                        } = {
                            level: 1,
                            order: order,
                            nodes: []
                        }
                        // 在li中，只能是P标签内容
                        const fn = (children: Node[], root: {
                            rootStyle: Record<string, boolean>,
                            rootFontSize: number,
                            rootColor: string | undefined
                        }) => {
                            const { rootStyle, rootFontSize, rootColor } = root
                            // 循环处理children
                            children.forEach(child => {
                                let _style: Record<string, boolean> = { ...rootStyle }
                                let _font_size = rootFontSize
                                let _color = rootColor
                                const attrs = child.attrs || {}
                                const styleStr = attrs.style || ''
                                const styleObj = handleStyleStrToObj(styleStr)
                                const classList: string[] = (attrs.class || '').split(' ') || []
                                if (Reflect.has(styleObj, 'text-decoration')) {
                                    _style.strikethrough = true
                                } if (Reflect.has(styleObj, 'color')) {
                                    _color = styleObj['color']
                                }
                                classList.forEach(c => {
                                    if (Reflect.has(class_color_map, c)) {
                                        _color = class_color_map[c as keyof typeof class_color_map]
                                    }
                                    if (Reflect.has(class_font_size_map, c)) {
                                        _font_size = class_font_size_map[c as keyof typeof class_font_size_map]
                                    }
                                })

                                if (child.name) {
                                    if ('strong' === child.name) {
                                        _style.bold = true
                                    } else if ('em' === child.name) {
                                        _style.italic = true
                                    } else if ('s' === child.name) {
                                        _style.strikethrough = true
                                    }
                                    if ('a' === child.name && child.children?.length) {
                                        // 链接类型
                                        const { children, attrs } = child
                                        const textnode = children[0]
                                        const href = attrs?.href || ''
                                        const text = textnode.text || ''
                                        if (textnode && text && href) {
                                            listItem!.nodes.push({
                                                type: 'TEXT_NODE_TYPE_RICH',
                                                rich: {
                                                    jump_url: href,
                                                    orig_text: href,
                                                    style: {},
                                                    text: text,
                                                    type: 'RICH_TEXT_NODE_TYPE_WEB',
                                                }
                                            })
                                        }
                                        return
                                    }
                                }
                                if (child.text || 'br' === child.name) {
                                    listItem.nodes.push({
                                        type: 'TEXT_NODE_TYPE_WORD',
                                        word: removeObjectEmptyValue({
                                            words: child.text || '\n',
                                            color: _color,
                                            font_size: _font_size,
                                            style: _style
                                        })
                                    })
                                } else if (child.children?.length) {
                                    // 进入下一次遍历children
                                    fn(child.children, { rootStyle: _style, rootFontSize: _font_size, rootColor: _color })
                                }
                            })
                        }
                        fn(child.children, { rootStyle: {}, rootFontSize: DEFAULT_FONT_SIZE, rootColor: undefined })
                        pItem.list!.items.push(listItem)
                    }
                })
                pargraphs.push(pItem)
            } else if ('figure' === node.name && node.children?.length) {
                // console.log(node)
                // 可能是图片组
                const pItem: ParagraphItem = {
                    align: 0,
                    para_type: PARA_TYPE.IMAGE,
                    pic: {
                        pics: [],
                        style: 2
                    }
                }
                for (let child of node.children) {
                    const { attrs } = child
                    const { class: className = '', src } = attrs || {}
                    const classList: string[] = (className || '').split(' ') || []
                    if (className.includes('cut-off')) {
                        const lineType = classList.find(c => c.includes('cut-off'))?.split('-')[2]
                        pargraphs.push({
                            align: 1,
                            para_type: PARA_TYPE.DIVIDER,
                            line: {
                                pic: {
                                    height: line_height_map[lineType as keyof typeof line_height_map],
                                    url: src,
                                }
                            },
                        })
                    } else if (className.includes('normal-img') || !className) {
                        const { height, width } = attrs || {}
                        pItem.pic!.pics.push({
                            height: Number(height),
                            live_url: null,
                            size: null,
                            url: src,
                            width: Number(width),
                        })
                    } else if (className.includes('game-card')) {
                        const { aid } = attrs || {}
                        // 使用异步获取详情，然后再赋值
                        const item: ParagraphItem = {
                            align: 0,
                            para_type: PARA_TYPE.LINK_CARD,
                            link_card: {
                                card: {
                                    common: {
                                        cover: '',
                                        desc1: '',
                                        desc2: '',
                                        head_text: '',
                                        id_str: '',
                                        jump_url: '',
                                        style: 1,
                                        sub_type: 'game',
                                        title: '',
                                    },
                                    type: 'LINK_CARD_TYPE_COMMON',
                                    oid: aid,
                                }
                            },
                        }
                        const res = await getGameCardDetail(aid)
                        const _data = res[aid]
                        Object.assign(item.link_card!.card!.common!, {
                            button: {
                                jump_style: {
                                    icon_url: _data.game_icon,
                                    text: '进入',
                                },
                                jump_url: _data.game_link,
                                type: 1,
                            },
                            cover: _data.cover,
                            desc1: _data.game_tags,
                            desc2: _data.notice,
                            head_text: _data.game_name,
                            id_str: _data.game_base_id,
                            jump_url: _data.game_link,
                            title: _data.game_name,
                        })
                        pargraphs.push(item)
                    } else if (className.includes('article-card')) {
                        const { aid } = attrs || {}
                        // 使用异步获取详情，然后再赋值
                        const item: ParagraphItem = {
                            align: 0,
                            para_type: PARA_TYPE.LINK_CARD,
                            link_card: {
                                card: {
                                    opus: {
                                        author: {
                                            mid: 0,
                                            name: ''
                                        },
                                        cover: '',
                                        jump_url: '',
                                        stat: {
                                            view: 0
                                        },
                                        title: ''
                                    },
                                    type: 'LINK_CARD_TYPE_OPUS',
                                    oid: aid,
                                }
                            },
                        }
                        const res = await getArticleDetail(aid)
                        const _data = res[aid]
                        Object.assign(item.link_card!.card!.opus!, {
                            author: {
                                mid: _data.author.mid,
                                name: _data.author.name,
                            },
                            cover: _data.image_urls?.[0] || '',
                            jump_url: `https://www.bilibili.com/read/${aid}`,
                            stat: {
                                view: _data.stats.view
                            },
                            title: _data.title,
                        })
                        pargraphs.push(item)
                    }
                }
                pItem.pic?.pics.length && pargraphs.push(pItem)
            }
        }
    }
    return pargraphs
}

/** 段落类型 */
export enum PARA_TYPE {
    TEXT = 1,//文本类型
    IMAGE = 2,//图片类型
    DIVIDER = 3,//分割线类型
    BLOCKQUOTE = 4,//引用类型
    LIST = 5,//列表类型
    LINK_CARD = 6,//链接卡片类型
    HEADER1 = 7,//一级标题
    HEADER2 = 8,//二级标题
}
// 卡片内容类型
export type LINKCARD_TYPE = 'LINK_CARD_TYPE_OPUS' | 'LINK_CARD_TYPE_COMMON'
// 卡片
export interface LINKCARD_CARD {
    common?: LINKCARD_CARD_COMMON,
    opus?: LINKCARD_CARD_OPUS,
    oid: string,//id
    type: LINKCARD_TYPE,//类型
}
// 常规卡片（游戏、
export interface LINKCARD_CARD_COMMON {
    button?: {
        jump_style: {
            icon_url: string,//图标链接
            text: string,//按钮文本
        },
        jump_url: string,//跳转链接
        type: number,//按钮类型
        status?: number,
        check?: {
            icon_url: string,//图标链接
            text: string,//按钮文本
        },
        uncheck?: {
            icon_url: string,//图标链接
            text: string,//按钮文本
        }
    },
    cover?: string,//封面
    desc1?: string,//描述1
    desc2?: string,//描述2
    head_text?: string,//标题
    id_str?: string,//id
    jump_url?: string,//跳转链接
    style?: number,//样式
    sub_type?: string,//子类型
    title?: string,//标题
    [key: string]: any,
}
// 文章卡片
export interface LINKCARD_CARD_OPUS {
    author?: {
        mid: number,//作者id
        name: string,//作者名
    },
    cover?: string,//文章封面
    jump_url?: string,//文章链接
    stat?: {
        view: number,//浏览量
    },
    title?: string//标题
}

/** 段落类型 */
export type TEXT_NODE_TYPE = "TEXT_NODE_TYPE_WORD" | "TEXT_NODE_TYPE_RICH"

export type RICH_TYPE = 'RICH_TEXT_NODE_TYPE_EMOJI' |
    'RICH_TEXT_NODE_TYPE_LOTTERY' |
    'RICH_TEXT_NODE_TYPE_VOTE' |
    'RICH_TEXT_NODE_TYPE_GOODS' |
    'RICH_TEXT_NODE_TYPE_CV' |
    'RICH_TEXT_NODE_TYPE_AV' |
    'RICH_TEXT_NODE_TYPE_BV' |
    'RICH_TEXT_NODE_TYPE_OGV_SEASON' |
    'RICH_TEXT_NODE_TYPE_OGV_EP' |
    'RICH_TEXT_NODE_TYPE_TAOBAO' |
    'RICH_TEXT_NODE_TYPE_WEB' |
    'RICH_TEXT_NODE_TYPE_AT' |
    'RICH_TEXT_NODE_TYPE_TOPIC'

export interface TextNode {
    type: TEXT_NODE_TYPE,
    word?: {
        font_size?: number, //字体大小 默认17
        font_level?: string, //字体等级 若存在则优先级比font_size高
        color?: string, //字体颜色
        style: {
            bold?: boolean,
            italic?: boolean,
            underline?: boolean,
            strikethrough?: boolean,
        },
        words: string,
    },
    rich?: {
        jump_url: string,
        orig_text: string,
        style?: {},
        text: string,
        type: RICH_TYPE,
        rid?: string,
    }
}

export interface ParagraphItem {
    align: number, //对齐方式 0-左对齐 1-居中 2-右对齐
    para_type: number, //段落类型 1-文本 2-图片 3-分割线 4-标题 5-列表 6-链接卡片
    text?: {
        nodes: TextNode[]
    },
    line?: {
        pic: {
            height: number,
            url: string,
        }
    },
    list?: {
        items: Array<{
            level: number,//列表层级 1-9 
            order: number,//排序
            nodes: TextNode[],
        }>,//实际编辑器生成不出嵌套列表
        style: number,//列表样式 1-有序列表 2-无序列表
    },
    pic?: {
        pics: {
            height: number,
            live_url: string | null,
            size: string | null,
            url: string,
            width: number,
        }[],
        style: number,//1-相册 2-单图
    },
    link_card?: {
        card: LINKCARD_CARD,
    }
}

const pargraphs: ParagraphItem[] = [
    {
        "align": 0,
        "para_type": 1,
        "text": {
            "nodes": [
                {
                    "type": "TEXT_NODE_TYPE_WORD",
                    "word": {
                        "font_size": 24,
                        "style": {
                            "bold": true
                        },
                        "words": "游戏介绍"
                    }
                }
            ]
        }
    },
    {
        "align": 0,
        "para_type": 4,
        "text": {
            "nodes": [
                {
                    "type": "TEXT_NODE_TYPE_WORD",
                    "word": {
                        "font_level": "regular",
                        "font_size": 17,
                        "style": {},
                        "words": "八位主角，八个冒险。在奥鲁斯特拉大陆，拥有不同能力的八位主角正展开一场新的冒险。玩家将成为其中一位主角，运用各自的技能，开始探索旅程，与敌人对战。成为商人亦或讨伐叛徒的战士，旅路上每一个路口、每一个选择，都引领旅人经历独一无二的冒险，想去哪里、和谁结成盟友，全部由玩家选择"
                    }
                }
            ]
        }
    },
    {
        "align": 1,
        "line": {
            "pic": {
                "height": 16,
                "url": "https://i0.hdslb.com/bfs/article/4adb9255ada5b97061e610b682b8636764fe50ed.png"
            }
        },
        "para_type": 3
    },
    {
        "align": 1,
        "para_type": 1,
        "text": {
            "nodes": [
                {
                    "type": "TEXT_NODE_TYPE_WORD",
                    "word": {
                        "color": "#fbe231",
                        "font_size": 17,
                        "style": {
                            "bold": true
                        },
                        "words": "欧菲莉亚"
                    }
                }
            ]
        }
    },
    {
        "align": 0,
        "para_type": 1,
        "text": {
            "nodes": [
                {
                    "type": "TEXT_NODE_TYPE_WORD",
                    "word": {
                        "font_size": 17,
                        "style": {},
                        "words": "建议"
                    }
                },
                {
                    "type": "TEXT_NODE_TYPE_WORD",
                    "word": {
                        "color": "#ee230d",
                        "font_size": 24,
                        "style": {},
                        "words": "前期必选"
                    }
                },
                {
                    "type": "TEXT_NODE_TYPE_WORD",
                    "word": {
                        "font_size": 17,
                        "style": {
                            "strikethrough": true
                        },
                        "words": "（"
                    }
                },
                {
                    "type": "TEXT_NODE_TYPE_WORD",
                    "word": {
                        "font_size": 24,
                        "style": {
                            "strikethrough": true
                        },
                        "words": "不是"
                    }
                },
                {
                    "type": "TEXT_NODE_TYPE_WORD",
                    "word": {
                        "font_size": 17,
                        "style": {
                            "strikethrough": true
                        },
                        "words": "）"
                    }
                }
            ]
        }
    },
    {
        "align": 0,
        "list": {
            "items": [
                {
                    "level": 1,
                    "nodes": [
                        {
                            "type": "TEXT_NODE_TYPE_WORD",
                            "word": {
                                "font_level": "regular",
                                "font_size": 17,
                                "style": {},
                                "words": "职业："
                            }
                        },
                        {
                            "type": "TEXT_NODE_TYPE_WORD",
                            "word": {
                                "font_level": "large",
                                "font_size": 20,
                                "style": {},
                                "words": "神官"
                            }
                        }
                    ],
                    "order": 1
                },
                {
                    "level": 1,
                    "nodes": [
                        {
                            "type": "TEXT_NODE_TYPE_WORD",
                            "word": {
                                "font_level": "regular",
                                "font_size": 17,
                                "style": {},
                                "words": "地图"
                            }
                        },
                        {
                            "type": "TEXT_NODE_TYPE_WORD",
                            "word": {
                                "font_level": "regular",
                                "font_size": 17,
                                "style": {},
                                "words": "指令"
                            }
                        },
                        {
                            "type": "TEXT_NODE_TYPE_WORD",
                            "word": {
                                "font_level": "regular",
                                "font_size": 17,
                                "style": {},
                                "words": "："
                            }
                        },
                        {
                            "type": "TEXT_NODE_TYPE_WORD",
                            "word": {
                                "font_level": "large",
                                "font_size": 20,
                                "style": {},
                                "words": "引导"
                            }
                        }
                    ],
                    "order": 2
                },
                {
                    "level": 1,
                    "nodes": [
                        {
                            "type": "TEXT_NODE_TYPE_WORD",
                            "word": {
                                "font_level": "regular",
                                "font_size": 17,
                                "style": {},
                                "words": "特有"
                            }
                        },
                        {
                            "type": "TEXT_NODE_TYPE_WORD",
                            "word": {
                                "font_level": "regular",
                                "font_size": 17,
                                "style": {},
                                "words": "动作"
                            }
                        },
                        {
                            "type": "TEXT_NODE_TYPE_WORD",
                            "word": {
                                "font_level": "regular",
                                "font_size": 17,
                                "style": {},
                                "words": "："
                            }
                        },
                        {
                            "type": "TEXT_NODE_TYPE_WORD",
                            "word": {
                                "font_level": "large",
                                "font_size": 20,
                                "style": {},
                                "words": "援助"
                            }
                        }
                    ],
                    "order": 3
                },
                {
                    "level": 4,
                    "nodes": [
                        {
                            "type": "TEXT_NODE_TYPE_WORD",
                            "word": {
                                "font_level": "regular",
                                "font_size": 17,
                                "style": {},
                                "words": "职业："
                            }
                        },
                        {
                            "type": "TEXT_NODE_TYPE_WORD",
                            "word": {
                                "font_level": "large",
                                "font_size": 20,
                                "style": {},
                                "words": "神官"
                            }
                        }
                    ],
                    "order": 1
                },
            ],
            "style": 2
        },
        "para_type": 5
    },
    {
        "align": 0,
        "para_type": 1,
        "text": {
            "nodes": [
                {
                    "rich": {
                        "jump_url": "https://www.bilibili.com/opus/1068533312894533656",
                        "orig_text": "https://www.bilibili.com/opus/1068533312894533656",
                        "style": {},
                        "text": "歧路旅人 大陆霸者游戏介绍 - 哔哩哔哩",
                        "type": "RICH_TEXT_NODE_TYPE_WEB"
                    },
                    "type": "TEXT_NODE_TYPE_RICH"
                }
            ]
        }
    },
    {
        "align": 0,
        "para_type": 2,
        "pic": {
            "pics": [
                {
                    "height": 983,
                    "live_url": null,
                    "size": null,
                    "url": "https://i0.hdslb.com/bfs/new_dyn/a78eb74b2e43b1e6a8eda18fd035343a140686110.webp",
                    "width": 1908
                }
            ],
            "style": 2
        }
    },
    {
        "align": 0,
        "para_type": 1,
        "text": {
            "nodes": [
                {
                    "type": "TEXT_NODE_TYPE_WORD",
                    "word": {
                        "font_size": 17,
                        "style": {},
                        "words": "\n"
                    }
                }
            ]
        }
    },
    {
        "align": 0,
        "link_card": {
            "card": {
                "common": {
                    "button": {
                        "jump_style": {
                            "icon_url": "",
                            "text": "进入"
                        },
                        "jump_url": "https://www.biligame.com/detail?id=111346&sourceFrom=1005",
                        "type": 1
                    },
                    "cover": "https://i0.hdslb.com/bfs/game/1fc7ff42ae247ca3a9da434f21657fa47623859a.png",
                    "desc1": "角色扮演/日式/像素",
                    "desc2": "经典王道日式RPG《歧路旅人》前传",
                    "head_text": "",
                    "id_str": "111346",
                    "jump_url": "https://www.biligame.com/detail?id=111346&sourceFrom=1005",
                    "style": 1,
                    "sub_type": "game",
                    "title": "歧路旅人：大陆的霸者"
                },
                "oid": "111346",
                "type": "LINK_CARD_TYPE_COMMON"
            }
        },
        "para_type": 6
    }, {
        "align": 0,
        "link_card": {
            "card": {
                "oid": "41725989",
                "opus": {
                    "author": {
                        "mid": 140686110,
                        "name": "言言_Official"
                    },
                    "cover": "https://i0.hdslb.com/bfs/new_dyn/banner/4a62f608ee3d8438f4d54db0dfb67d40140686110.png",
                    "jump_url": "//www.bilibili.com/read/cv41725989/",
                    "stat": {
                        "view": 47
                    },
                    "title": "歧路旅人 大陆霸者游戏介绍"
                },
                "type": "LINK_CARD_TYPE_OPUS"
            }
        },
        "para_type": 6
    }
]
// https://api.bilibili.com/x/article/cards?ids=gm111346&game_sdk_type=1
export const getGameCardDetail = (id: string) => {
    return Promise.resolve({
        [id]: {
            "game_base_id": 111346,
            "is_online": true,
            "game_name": "歧路旅人：大陆的霸者",
            "cover": "http://192.168.2.219:9000/smart-park/upload/20250521/d698b94bd4db9eeadfdc8300651221ff.png",
            "game_icon": "https://i0.hdslb.com/bfs/game/1fc7ff42ae247ca3a9da434f21657fa47623859a.png",
            "game_status": 0,
            "game_link": "bilibili://game_center/detail?id=111346&sourceType=adPut",
            "grade_status": 2,
            "grade": 7.9,
            "book_num": 0,
            "game_tags": "角色扮演/日式/像素",
            "download_num": 204342,
            "notice": "经典王道日式RPG《歧路旅人》前传",
            "follower_num": 196169,
            "summary": "一周年庆典开启中！回忆时光，启程新章。"
        }
    })

}
export const getArticleDetail = (itemId: string) => {
    // 请求接口获取卡片信息
    return Promise.resolve({
        [itemId]: {
            act_id: 0,
            apply_time: "",
            attributes: 24,
            authenMark: null,
            author: {
                face: "https://i1.hdslb.com/bfs/face/c6712277697434a6dc40c0185c0108c39b2fc6fa.jpg",
                fans: 0,
                level: 0,
                mid: 37090048,
                name: "哔哩哔哩创作中心",
                nameplat: {
                    condition: "累计开通大会员总时长>=10年即可获得",
                    image: "https://i0.hdslb.com/bfs/face/5b04cc2fb1c479874cac145eb7ac7098a1e081d9.png",
                    image_small: "https://i1.hdslb.com/bfs/face/b44b390de6b68a9ac7087b3bef07ad90a46101c4.png",
                    level: "稀有勋章",
                    name: "十年大会员",
                    nid: 88
                },
                official_verify: {
                    desc: "哔哩哔哩创作中心官方账号",
                    type: 1,
                },
                pendant: {
                    expire: 0,
                    image: "",
                    name: "",
                    pid: 0
                },
                vip: {
                    avatar_subscript: 1,
                    due_date: 0,
                    label: {
                        label_theme: "ten_annual_vip",
                        path: 'http://i0.hdslb.com/bfs/vip/label_annual.png',
                        text: "十年大会员",
                    },
                    nickname_color: "#FB7299",
                    status: 1,
                    theme_type: 0,
                    type: 2,
                    vip_pay_type: 0,
                }
            },
            banner_url: "https://i0.hdslb.com/bfs/article/cd504bd19ea5a5c67bddb67f221e223778f2a677.jpg",
            categories: [{
                id: 3,
                name: "生活",
                parent_id: 0
            }, {
                id: 15,
                name: "日常",
                parent_id: 3
            }],
            category: {
                id: 15,
                name: "日常",
                parent_id: 3
            },
            check_state: 0,
            check_time: "",
            content_pipc_list: null,
            cover_avid: 0,
            ctime: 1617168647,
            dispute: null,
            id: 10555126,
            image_urls: ['http://192.168.2.219:9000/smart-park/upload/20250521/d698b94bd4db9eeadfdc8300651221ff.png'],
            is_like: false,
            list: {
                apply_time: "",
                articles_count: 0,
                check_time: "",
                ctime: 1540541319,
                id: 33550,
                image_url: "http://i0.hdslb.com/bfs/article/acd0988083e12d9149742dd45a82fe84023ba8e9.png",
                mid: 37090048,
                name: "功能宣发",
                publish_time: 1739865422,
                read: 0,
                reason: "",
                state: 1,
                summary: "产品上线、功能宣发",
                update_time: 1739865387,
                words: 40705,
            },
            media: {
                area: "",
                cover: "",
                media_id: 0,
                score: 0,
                season_id: 0,
                spoiler: 0,
                title: "",
                type_id: 0,
                type_name: "",
            },
            mtime: 1634094301,
            origin_image_urls: ['https://i0.hdslb.com/bfs/article/801bb0ffc9be3a064b6489f2f12bcdcd22c1cbc2.png'],
            origin_template_id: 4,
            original: 1,
            private_pub: 0,
            publish_time: 1617168647,
            reprint: 0,
            state: 0,
            stats: {
                coin: 47,
                dislike: 0,
                dynamic: 0,
                favorite: 542,
                like: 2969,
                reply: 235,
                share: 199,
                view: 997549,
            },
            summary: "亲爱的UP主们创作君又为大家带来新功能【UP主稿件预约】啦~什么是UP主稿件预约？UP主稿件预约是一个预告未来稿件更新的功能稿件更新时会通知已预约的用户前来观看！UP主稿件预约怎么用？UP主电磁力到达Lv4后，就可以使用稿件预约（App端需更新至6.21.0及以上版本）UP主发布稿件预约后，在UP主动态、空间等位置会展示预约信息，用户可点击预约。UP主发布稿件时，需关联预约信息（目前仅支持App端），才能对已预约的观众进行稿件更新提醒。如果UP主撤销预约，已预约的观众将收到预约撤销提醒。UP主如",
            template_id: 4,
            title: "【功能介绍】UP主稿件预约上线啦！",
            top_video_info: null,
            type: 0,
            words: 545,
        },
    })
}
// 设置对象的属性
export const setObjectProperty = (
    obj: Record<string, any>,
    key: string,
    value: any
) => {
    key in obj
        ? Object.defineProperty(obj, key, {
            value,
            enumerable: false,
            configurable: false,
            writable: false,
        })
        : (obj[key] = value)
    return obj
}



/**------------------------------------- */
export const styleObjectToString = (style: Record<string, string>) => {
    const list: string[] = []
    Object.keys(style).forEach(key => {
        list.push(`${key}:${style[key]}`)
    })
    return list.join(';')
}
interface DeltaContent {
    ops: DeltaOperation[]
}
// 自定义blot类型设置为块级的类型名
const customBlotToBlockType = ['native-image', 'article-card', 'video-card', 'game-card', 'mall-card', 'live-card', 'cut-off']
export const handleDeltaToHtml = (delta: DeltaContent) => {
    // 预处理delta，对自定义blot类型属于块类型的添加renderAsBlock:true属性，识别为块级
    delta.ops.forEach(item => {
        if (item.insert && 'string' !== item.insert) {
            const _type = Object.keys(item.insert)[0]
            if (customBlotToBlockType.includes(_type)) {
                if (item.attributes) {
                    Object.assign(item.attributes, { renderAsBlock: true })
                } else item.attributes = { renderAsBlock: true }
            }
        }
    })
    const converter = new QuillDeltaToHtmlConverter(delta.ops, {
        multiLineParagraph: false,//换行符不转换为<br>
    })
    converter.renderCustomWith((customOp) => {
        const { insert, attributes } = customOp
        if (insert.type === 'cut-off') {
            const { type } = insert.value
            return `<figure class="img-box" contenteditable="false"><img class="cut-off-${1 + Number(type)}" src="${insert.value.url}"></figure>`
        } else if (insert.type === 'article-card') {
            return `<figure class="img-box" contenteditable="false"><img width="${insert.value.width}" height="${insert.value.height}" aid="${insert.value.id}" class="${attributes.class}" type="normal"></figure>`
        } else if (insert.type === 'video-card') {
            // return 'video-card'
            return `<figure class="img-box" contenteditable="false"><img width="${insert.value.width}" height="${insert.value.height}" aid="${insert.value.id}" class="game-card" type="normal"></figure>`
        } else if (insert.type === 'live-card') {
            // return 'live-card'
            return `<figure class="img-box" contenteditable="false"><img width="${insert.value.width}" height="${insert.value.height}" aid="${insert.value.id}" class="game-card" type="normal"></figure>`
        } else if (insert.type === 'mall-card') {
            // return 'mall-card'
            return `<figure class="img-box" contenteditable="false"><img width="${insert.value.width}" height="${insert.value.height}" aid="${insert.value.id}" class="game-card" type="normal"></figure>`
        } else if (insert.type === 'native-image') {
            return `<figure class="img-box" contenteditable="false"><img class="${attributes.class}" style="width:${insert.value.width}px;height:${insert.value.height}px;" width="${insert.value.width}" height="${insert.value.height}" alt="${insert.value.alt}" src="${insert.value.src}" size="${insert.value.size}"></figure>`
        }
        return ''
    })
    return converter.convert()
}
